/// API服务
/// 提供与后端API的通信
library;

import 'dart:convert';
import 'package:http/http.dart' as http;
import 'package:chat_project/config/api_config.dart';
import 'package:chat_project/services/storage_service.dart';

class ApiService {
  final StorageService _storageService = StorageService();
  final bool _useMockData = false; // 使用真实API数据
  
  // 控制是否使用模拟数据的方法
  bool shouldUseMockData(bool? forceMock) {
    // 如果强制指定了模拟状态，使用指定状态
    if (forceMock != null) {
      return forceMock;
    }
    // 否则使用默认设置
    return _useMockData;
  }

  // HTTP客户端
  http.Client get _client => http.Client();

  // 设置请求头
  Future<Map<String, String>> _getHeaders() async {
    final token = await _storageService.getToken();
    return {
      'Content-Type': 'application/json',
      'Authorization': token != null ? 'Bearer $token' : '',
    };
  }

  // 处理响应
  dynamic _handleResponse(http.Response response) {
    print('处理HTTP响应: 状态码=${response.statusCode}');
    if (response.statusCode >= 200 && response.statusCode < 300) {
      if (response.body.isEmpty) return null;
      try {
        return json.decode(response.body);
      } catch (e) {
        print('JSON解析错误: ${response.body}');
        throw '服务器返回了无效的数据格式';
      }
    } else {
      try {
        final error = json.decode(response.body);
        throw error['message'] ?? '请求失败 (${response.statusCode})';
      } catch (e) {
        if (e is FormatException) {
          print('无法解析错误响应: ${response.body}');
          throw '服务器错误 (${response.statusCode})';
        }
        rethrow;
      }
    }
  }

  // 发送HTTP请求并支持重试
  Future<http.Response> _sendRequest(Future<http.Response> Function() requestFunc) async {
    const maxRetries = 3;
    const retryDelay = Duration(seconds: 1);
    
    for (int i = 0; i < maxRetries; i++) {
      try {
        return await requestFunc();
      } catch (e) {
        print('HTTP请求失败(尝试 ${i+1}/$maxRetries): $e');
        if (i == maxRetries - 1) rethrow;
        await Future.delayed(retryDelay * (i + 1));
      }
    }
    
    // 不应该到达这里，但为了满足Dart类型检查
    throw '请求失败，已达到最大重试次数';
  }

  // 用户登录
  Future<Map<String, dynamic>> login(String username, String password, {bool? forceMock}) async {
    if (shouldUseMockData(forceMock)) {
      await Future.delayed(const Duration(seconds: 1)); // 模拟网络延迟
      
      // 在模拟模式下，任何用户名和密码都允许登录
      // 简单验证，密码至少需要6个字符
      if (password.length < 6) {
        throw '密码至少需要6个字符';
      }
      
      final mockToken = 'mock_token_${DateTime.now().millisecondsSinceEpoch}';
      
      // 保存令牌到本地存储
      await _storageService.saveToken(mockToken);
      
      return {
        '_id': '1',
        'username': username,
        'email': '$username@example.com',
        'avatar': 'https://ui-avatars.com/api/?name=${username[0]}&background=random',
        'token': mockToken,
      };
    }

    try {
      print('尝试登录: $username');
      final url = Uri.parse(ApiConfig.loginUrl);
      print('登录URL: $url');
      
      final response = await _sendRequest(() => _client.post(
        url,
        headers: {'Content-Type': 'application/json'},
        body: json.encode({
          'usernameOrEmail': username,
          'password': password,
        }),
      ));
      
      print('登录响应状态码: ${response.statusCode}');
      print('登录响应内容: ${response.body}');
      
      final data = _handleResponse(response);
      
      // 确保数据中包含token
      if (data['token'] != null) {
        print('获取到令牌: ${data['token'].substring(0, 10)}...');
        // 保存令牌到本地存储
        await _storageService.saveToken(data['token']);
      } else {
        print('警告: 后端返回数据中不包含token');
      }
      
      return data;
    } catch (e) {
      print('登录失败: $e');
      rethrow;
    }
  }

  // 用户注册
  Future<Map<String, dynamic>> register(
      String username, String email, String password, {bool? forceMock}) async {
    if (shouldUseMockData(forceMock)) {
      await Future.delayed(const Duration(seconds: 1)); // 模拟网络延迟
      
      // 在模拟模式下，执行基本验证
      if (username.length < 3) {
        throw '用户名至少需要3个字符';
      }
      
      if (password.length < 6) {
        throw '密码至少需要6个字符';
      }
      
      final emailRegex = RegExp(r'^[\w-\.]+@([\w-]+\.)+[\w-]{2,4}$');
      if (!emailRegex.hasMatch(email)) {
        throw '请输入有效的邮箱地址';
      }
      
      final mockToken = 'mock_token_${DateTime.now().millisecondsSinceEpoch}';
      
      // 保存令牌到本地存储
      await _storageService.saveToken(mockToken);
      
      return {
        '_id': '1',
        'username': username,
        'email': email,
        'avatar': 'https://ui-avatars.com/api/?name=${username[0]}&background=random',
        'token': mockToken,
      };
    }

    try {
      print('尝试注册: username=$username, email=$email');
      final url = Uri.parse(ApiConfig.registerUrl);
      print('注册URL: $url');
      
      final response = await _sendRequest(() => _client.post(
        url,
        headers: {'Content-Type': 'application/json'},
        body: json.encode({
          'username': username,
          'email': email,
          'password': password,
        }),
      ));
      
      print('注册响应状态码: ${response.statusCode}');
      print('注册响应内容: ${response.body}');
      
      final data = _handleResponse(response);
      
      // 确保数据中包含token
      if (data['token'] != null) {
        print('获取到令牌: ${data['token'].substring(0, 10)}...');
        // 保存令牌到本地存储
        await _storageService.saveToken(data['token']);
      } else {
        print('警告: 后端返回数据中不包含token');
      }
      
      return data;
    } catch (e) {
      print('注册失败: $e');
      rethrow;
    }
  }

  // 获取当前用户信息
  Future<Map<String, dynamic>> getCurrentUser() async {
    if (shouldUseMockData(null)) {
      await Future.delayed(const Duration(seconds: 1)); // 模拟网络延迟
      const username = 'user1';
      return {
        '_id': '1',
        'username': username,
        'email': '$username@example.com',
        'avatar': 'https://ui-avatars.com/api/?name=$username&background=random&format=png',
        'bio': '这是一个测试用户',
        'isOnline': true,
        'lastSeen': DateTime.now().toIso8601String(),
      };
    }

    final response = await _client.get(
      Uri.parse('${ApiConfig.baseUrl}/api/auth/me'),
      headers: await _getHeaders(),
    );
    return _handleResponse(response);
  }

  // 获取用户会话列表
  Future<List<dynamic>> getConversations() async {
    if (shouldUseMockData(null)) {
      await Future.delayed(const Duration(seconds: 1)); // 模拟网络延迟

      final List<Map<String, dynamic>> mockConversations = [];

      // 模拟10个对话
      for (int i = 1; i <= 10; i++) {
        final username = 'user$i';

        mockConversations.add({
          'id': 'conv_$i',
          'contact': {
            'id': 'user_$i',
            'username': username,
            'email': '$username@example.com',
            'avatar':
                'https://ui-avatars.com/api/?name=$username&background=random&format=png',
            'isOnline': i % 3 == 0, // 每3个用户中有1个在线
            'lastSeen': DateTime.now()
                .subtract(Duration(minutes: i * 5))
                .toIso8601String(),
          },
          'lastMessage': i % 4 == 0
              ? null
              : {
                  'id': 'msg_${i}_${DateTime.now().millisecondsSinceEpoch}',
                  'content': '这是一条测试消息 $i',
                  'type': 'text',
                  'sender': {
                    'id': i % 2 == 0 ? '1' : 'user_$i',
                    'username': i % 2 == 0 ? 'user1' : username,
                    'avatar': i % 2 == 0
                        ? 'https://ui-avatars.com/api/?name=user1&background=random&format=png'
                        : 'https://ui-avatars.com/api/?name=$username&background=random&format=png',
                  },
                  'createdAt': DateTime.now()
                      .subtract(Duration(minutes: i * 10))
                      .toIso8601String(),
                  'status': 'delivered',
                },
          'unreadCount': i % 3 == 0 ? i : 0, // 有些对话有未读消息
          'updatedAt': DateTime.now()
              .subtract(Duration(minutes: i * 10))
              .toIso8601String(),
        });
      }

      return mockConversations;
    }

    // 非模拟模式下的实际API调用
    final response = await _client.get(
      Uri.parse('${ApiConfig.baseUrl}/api/conversations'),
      headers: await _getHeaders(),
    );
    return _handleResponse(response);
  }

  // 获取与特定用户的消息历史
  Future<List<dynamic>> getMessages(String userId, {String? conversationId}) async {
    if (shouldUseMockData(null)) {
      await Future.delayed(const Duration(seconds: 1)); // 模拟网络延迟

      final List<Map<String, dynamic>> mockMessages = [];

      // 模拟20条消息记录
      for (int i = 1; i <= 20; i++) {
        final isSelf = i % 2 == 0;
        final username = isSelf ? 'user1' : 'user$userId';
        final timestamp =
            DateTime.now().subtract(Duration(minutes: (20 - i) * 10));

        mockMessages.add({
          'id': 'msg_${i}_${timestamp.millisecondsSinceEpoch}',
          'content': '这是第 $i 条测试消息',
          'type': 'text',
          'sender': {
            'id': isSelf ? '1' : userId,
            'username': username,
            'avatar':
                'https://ui-avatars.com/api/?name=$username&background=random&format=png',
          },
          'receiverId': isSelf ? userId : '1',
          'status': 'read',
          'createdAt': timestamp.toIso8601String(),
        });
      }

      return mockMessages;
    }

    try {
      // 确保userId是简单字符串 - 这一步非常重要
      final String safeUserId = _extractSafeId(userId);
      
      // 优先使用会话ID访问API (服务器正确的接口)
      String? safeConversationId;
      if (conversationId != null && conversationId.isNotEmpty) {
        safeConversationId = _extractSafeId(conversationId);
        print('使用会话ID $safeConversationId 请求消息历史');
        
        final url = Uri.parse('${ApiConfig.baseUrl}/api/conversations/$safeConversationId/messages');
        final response = await _client.get(url, headers: await _getHeaders());
        
        if (response.statusCode == 404) {
          print('没有找到会话 $safeConversationId 的消息历史，返回空列表');
          return [];
        }
        
        final data = _handleResponse(response);
        // 服务器返回的格式可能是 {messages: [...]} 或直接是消息数组
        return data is Map ? (data['messages'] ?? []) : data;
      }
      
      // 回退到用户ID接口 (可能不存在此接口)
      print('找不到会话ID，使用用户ID请求消息: $safeUserId');
      final response = await _client.get(
        Uri.parse('${ApiConfig.baseUrl}/api/messages/user/$safeUserId'),
        headers: await _getHeaders(),
      );
      
      // 处理404错误
      if (response.statusCode == 404) {
        print('没有找到与用户 $safeUserId 的消息历史，返回空列表');
        return []; // 返回空列表而不是抛出异常
      }
      
      return _handleResponse(response);
    } catch (e) {
      print('获取消息历史时发生错误: $e');
      
      // 返回空列表而不是重新抛出异常，确保UI不会崩溃
      return [];
    }
  }
  
  // 辅助方法-提取安全ID
  String _extractSafeId(String id) {
    print('提取安全ID: ${id.runtimeType}, 值: $id');
    
    if (id.contains('{') || id.contains('}') || id.contains(':')) {
      // 尝试提取ID - 假设格式如 {_id: xxxx, ...} 或 JSON格式
      final idMatch = RegExp(r"_id:\s*([^\s,}]+)").firstMatch(id);
      if (idMatch != null && idMatch.groupCount > 0) {
        final safeId = idMatch.group(1)!.trim();
        print('从复杂对象中提取ID: $safeId');
        return safeId;
      }
      
      // 第二种尝试 - "_id":"xxxx" JSON格式
      final jsonMatch = RegExp(r'"_id"\s*:\s*"([^"]+)"').firstMatch(id);
      if (jsonMatch != null && jsonMatch.groupCount > 0) {
        final safeId = jsonMatch.group(1)!.trim();
        print('从JSON中提取ID: $safeId');
        return safeId;
      }
      
      print('警告: 无法从复杂对象中提取ID: $id');
      // 返回原值而不是抛出异常
      return id;
    }
    return id;
  }

  // 发送消息
  Future<Map<String, dynamic>> sendMessage(
      String receiverId, String content, String type, {String? conversationId}) async {
    if (shouldUseMockData(null)) {
      await Future.delayed(const Duration(seconds: 1)); // 模拟网络延迟

      final timestamp = DateTime.now();
      return {
        'id': 'msg_${timestamp.millisecondsSinceEpoch}',
        'content': content,
        'type': type,
        'sender': {
          'id': '1',
          'username': 'user1',
          'avatar': 'https://ui-avatars.com/api/?name=user1&background=random&format=png',
        },
        'receiverId': receiverId,
        'status': 'sent',
        'createdAt': timestamp.toIso8601String(),
      };
    }

    try {
      // 确保receiverId是一个简单字符串
      final String safeReceiverId = _extractSafeId(receiverId);
      
      // 准备请求数据
      final Map<String, dynamic> requestData = {
        'content': content,
        'type': type,
      };
      
      // 根据是否有conversationId决定使用哪个API
      final Uri url;
      if (conversationId != null && conversationId.isNotEmpty) {
        final String safeConversationId = _extractSafeId(conversationId);
        print('使用会话ID $safeConversationId 发送消息');
        requestData['conversationId'] = safeConversationId;
        url = Uri.parse('${ApiConfig.baseUrl}/api/messages');
      } else {
        print('使用接收者ID发送消息: $safeReceiverId');
        requestData['receiverId'] = safeReceiverId;
        url = Uri.parse('${ApiConfig.baseUrl}/api/messages/send');
      }
      
      // 非模拟模式下的实际API调用
      final response = await _client.post(
        url,
        headers: await _getHeaders(),
        body: json.encode(requestData),
      );
      
      // 处理404错误
      if (response.statusCode == 404) {
        print('发送消息API未找到，返回模拟消息数据');
        // 创建临时消息响应
        final timestamp = DateTime.now();
        return {
          'id': 'temp_local_${timestamp.millisecondsSinceEpoch}',
          'content': content,
          'type': type,
          'sender': {
            'id': await _getCurrentUserId(),
            'username': 'current_user',
            'avatar': 'https://ui-avatars.com/api/?name=U&background=random&format=png',
          },
          'receiverId': safeReceiverId,
          'status': 'sent',
          'createdAt': timestamp.toIso8601String(),
        };
      }
      
      return _handleResponse(response);
    } catch (e) {
      print('发送消息时发生错误: $e');
      
      // 返回模拟消息数据，以免UI崩溃
      final timestamp = DateTime.now();
      return {
        'id': 'error_${timestamp.millisecondsSinceEpoch}',
        'content': content,
        'type': type,
        'sender': {
          'id': '1', // 假设当前用户ID
          'username': 'current_user',
          'avatar': 'https://ui-avatars.com/api/?name=U&background=random&format=png',
        },
        'receiverId': receiverId,
        'status': 'error',
        'createdAt': timestamp.toIso8601String(),
      };
    }
  }

  // 获取当前用户ID
  Future<String> _getCurrentUserId() async {
    try {
      final user = await _storageService.getUser();
      return user?.id ?? '1';
    } catch (e) {
      return '1';
    }
  }

  // 标记对话为已读
  Future<void> markConversationAsRead(String conversationId) async {
    if (shouldUseMockData(null)) {
      await Future.delayed(const Duration(milliseconds: 500)); // 模拟网络延迟
      return;
    }

    final response = await _client.put(
      Uri.parse('${ApiConfig.baseUrl}/api/conversations/$conversationId/read'),
      headers: await _getHeaders(),
    );
    _handleResponse(response);
  }

  // 更新用户信息
  Future<Map<String, dynamic>> updateUserProfile(
      Map<String, dynamic> data) async {
    if (shouldUseMockData(null)) {
      await Future.delayed(const Duration(seconds: 1)); // 模拟网络延迟

      return {
        '_id': '1',
        'username': data['username'] ?? 'user1',
        'email': 'user1@example.com',
        'avatar': data['avatar'] ??
            'https://ui-avatars.com/api/?name=user1&background=random&format=png',
        'bio': data['bio'] ?? '这是一个测试用户',
        'isOnline': true,
        'lastSeen': DateTime.now().toIso8601String(),
      };
    }

    final response = await _client.put(
      Uri.parse('${ApiConfig.baseUrl}/api/users/profile'),
      headers: await _getHeaders(),
      body: json.encode(data),
    );
    return _handleResponse(response);
  }

  // 上传头像
  Future<Map<String, dynamic>> uploadAvatar(String filePath) async {
    if (shouldUseMockData(null)) {
      await Future.delayed(const Duration(seconds: 2)); // 模拟网络延迟
      return {
        '_id': '1',
        'username': 'user1',
        'avatar':
            'https://ui-avatars.com/api/?name=user1&background=random&format=png',
      };
    }

    // 创建multipart请求
    final request = http.MultipartRequest(
      'POST',
      Uri.parse('${ApiConfig.baseUrl}/api/users/avatar'),
    );

    // 添加token
    final token = await _storageService.getToken();
    request.headers['Authorization'] = 'Bearer $token';

    // 添加文件
    request.files.add(await http.MultipartFile.fromPath('avatar', filePath));

    // 发送请求
    final streamedResponse = await request.send();
    final response = await http.Response.fromStream(streamedResponse);

    return _handleResponse(response);
  }

  // 搜索用户
  Future<List<dynamic>> searchUsers(String keyword) async {
    if (shouldUseMockData(null)) {
      await Future.delayed(const Duration(seconds: 1)); // 模拟网络延迟

      final List<Map<String, dynamic>> mockUsers = [];

      // 模拟5个搜索结果
      for (int i = 1; i <= 5; i++) {
        final username = '${keyword}_user$i';
        mockUsers.add({
          'id': 'search_$i',
          'username': username,
          'email': '$username@example.com',
          'avatar': 'https://ui-avatars.com/api/?name=$username&background=random&format=png',
          'isOnline': i % 2 == 0,
          'lastSeen':
              DateTime.now().subtract(Duration(hours: i)).toIso8601String(),
        });
      }

      return mockUsers;
    }

    // 非模拟模式下的实际API调用
    final response = await _client.get(
      Uri.parse('${ApiConfig.baseUrl}/api/users/search?keyword=$keyword'),
      headers: await _getHeaders(),
    );
    return _handleResponse(response);
  }

  // 获取联系人列表
  Future<List<dynamic>> getContacts() async {
    if (shouldUseMockData(null)) {
      await Future.delayed(const Duration(seconds: 1)); // 模拟网络延迟
      
      // 新用户没有联系人，返回空列表
      return [];
    }
    
    // 真实API调用
    try {
      print('请求联系人列表');
      final response = await _sendRequest(() async {
        return _client.get(
          Uri.parse('${ApiConfig.baseUrl}/api/contacts'),
          headers: await _getHeaders(),
        );
      });
      
      print('联系人列表响应状态码: ${response.statusCode}');
      print('联系人列表响应内容: ${response.body}');
      
      final result = _handleResponse(response);
      // 确保返回的是列表
      if (result is List) {
        return result;
      } else {
        print('警告: 获取联系人列表返回的不是列表格式');
        return [];
      }
    } catch (e) {
      print('获取联系人列表失败: $e');
      return []; // 返回空列表而不是抛出异常
    }
  }
  
  // 添加联系人
  Future<Map<String, dynamic>> addContact(String userId) async {
    if (shouldUseMockData(null)) {
      await Future.delayed(const Duration(seconds: 1)); // 模拟网络延迟
      
      // 模拟新联系人数据
      final contact = {
        'id': userId,
        'username': 'user$userId',
        'email': 'user$userId@example.com',
        'avatar': 'https://ui-avatars.com/api/?name=user$userId&background=random&format=png',
        'bio': '这是用户$userId的个人简介',
        'isOnline': true,
        'lastSeen': DateTime.now().toIso8601String(),
      };
      
      // 模拟对话数据
      final conversation = {
        '_id': 'conv_${DateTime.now().millisecondsSinceEpoch}',
      };
      
      return {
        'contact': contact,
        'conversation': conversation,
      };
    }
    
    // 真实API调用
    try {
      print('请求添加联系人: $userId');
      final response = await _sendRequest(() async {
        return _client.post(
          Uri.parse('${ApiConfig.baseUrl}/api/contacts/add'),
          headers: await _getHeaders(),
          body: json.encode({
            'userId': userId,
          }),
        );
      });
      
      print('添加联系人响应状态码: ${response.statusCode}');
      print('添加联系人响应内容: ${response.body}');
      
      return _handleResponse(response);
    } catch (e) {
      print('添加联系人失败: $e');
      // 检查是否包含重复键错误信息
      if (e.toString().contains('E11000') || 
          e.toString().contains('已经是您的联系人')) {
        throw '该用户已经是您的联系人';
      }
      rethrow;
    }
  }
  
  // 移除联系人
  Future<void> removeContact(String contactId) async {
    if (shouldUseMockData(null)) {
      await Future.delayed(const Duration(seconds: 1)); // 模拟网络延迟
      return;
    }
    
    // 真实API调用
    try {
      print('请求移除联系人: $contactId');
      final response = await _sendRequest(() async {
        return _client.delete(
          Uri.parse('${ApiConfig.baseUrl}/api/contacts/$contactId'),
          headers: await _getHeaders(),
        );
      });
      
      print('移除联系人响应状态码: ${response.statusCode}');
      print('移除联系人响应内容: ${response.body}');
      
      _handleResponse(response);
    } catch (e) {
      print('移除联系人失败: $e');
      rethrow;
    }
  }
  
  // 获取或创建与联系人的对话
  Future<Map<String, dynamic>> getOrCreateConversation(String contactId) async {
    if (shouldUseMockData(null)) {
      await Future.delayed(const Duration(milliseconds: 500)); // 模拟网络延迟
      
      return {
        '_id': 'conv_${contactId}_${DateTime.now().millisecondsSinceEpoch}',
        'participants': ['user_1', contactId]
      };
    }
    
    // 真实API调用
    try {
      print('请求获取或创建对话: $contactId');
      // 确保contactId是有效的字符串ID
      String safeContactId = contactId;
      if (contactId.contains('{') || contactId.contains('}') || contactId.contains(':')) {
        safeContactId = _extractSafeId(contactId);
        print('提取安全联系人ID: $safeContactId');
      }
      
      final response = await _sendRequest(() async {
        return _client.post(
          Uri.parse('${ApiConfig.baseUrl}/api/contacts/conversation'),
          headers: await _getHeaders(),
          body: json.encode({
            'contactId': safeContactId,
          }),
        );
      });
      
      print('获取或创建对话响应状态码: ${response.statusCode}');
      print('获取或创建对话响应内容: ${response.body}');
      
      final data = _handleResponse(response);
      // 检查返回的数据格式是否正确
      if (data is Map<String, dynamic> && data.containsKey('_id')) {
        print('成功获取对话: ${data['_id']}');
        return data;
      } else {
        print('API返回的数据格式不正确: $data');
        throw '服务器返回了无效的对话数据';
      }
    } catch (e) {
      print('获取或创建对话失败: $e');
      // 创建一个临时对话ID作为fallback
      final tempId = 'temp_conv_${contactId}_${DateTime.now().millisecondsSinceEpoch}';
      print('创建临时对话ID作为fallback: $tempId');
      return {
        '_id': tempId,
        'participants': ['current_user', contactId]
      };
    }
  }
}

/// API异常
class ApiException implements Exception {
  final String message;
  final int statusCode;

  ApiException({required this.message, required this.statusCode});

  @override
  String toString() => message;
}
